import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by baoyunfeng on 2017/8/10.
 */
public class Generics {
    public static void main(String args[]){
        System.out.println("helloGenerics");
        Generics g = new Generics();
        g.genericErasure();
        g.genericReflect();
    }

    /**
     * 类型擦除
     * @return
     */
    private void genericErasure(){
        List<String> l1 = new ArrayList<>();
        List<Integer> l2 = new ArrayList<>();
        System.out.println("GenericRemove:"+(l1.getClass() == l2.getClass()));
    }

    private void genericReflect(){
        Erasure<String> erasure = new Erasure<>("hello");
        Class eclz = erasure.getClass();
        System.out.println("erasure class is: " + eclz.getName());
        Field[] fs = eclz.getDeclaredFields();
        for(Field field : fs){
            System.out.println("Field name :"+ field.getName() + " type:" + field.getType().getName());
            //Field name :t type:java.lang.Object
        }

        Method[] methods = eclz.getDeclaredMethods();
        for(Method m : methods){
            System.out.println(" method :" + m.toString());
            //method :public void Generics$Erasure.add(java.lang.Object)
        }

        try {
            Method method = erasure.getClass().getDeclaredMethod("add",Object.class);

            method.invoke(erasure,123);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        System.out.println(" erasure :" + (Object)erasure.t);

    }

    public class Erasure<T>{
        T t;

        public Erasure(T t) {
            this.t = t;
        }

        public void add(T t){
            this.t = t;
        }
    }

    public class ErasureWithString<T extends String>{
        T t;

        public ErasureWithString(T t) {
            this.t = t;
        }
    }
}
